const { logError } = require('../utils/logger');

/**
 * 处理404错误的中间件
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - Express下一个中间件函数
 */
const notFound = (req, res, next) => {
  const error = new Error(`未找到 - ${req.originalUrl}`);
  res.status(404);
  next(error);
};

/**
 * 处理验证错误的中间件
 * @param {Object} err - 错误对象
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - Express下一个中间件函数
 */
const validationErrorHandler = (err, req, res, next) => {
  // 检查是否为验证错误
  if (err.name === 'ValidationError') {
    // 格式化验证错误
    const errors = {};
    
    // 处理Mongoose验证错误
    if (err.errors) {
      Object.keys(err.errors).forEach((key) => {
        errors[key] = err.errors[key].message;
      });
    }
    
    // 处理Express-validator错误
    if (Array.isArray(err) && err.length > 0) {
      err.forEach((error) => {
        errors[error.param] = error.msg;
      });
    }
    
    // 记录验证错误
    logError(err, req);
    
    return res.status(400).json({
      message: '请求数据验证失败',
      errors,
    });
  }
  
  // 不是验证错误，传递给下一个错误处理中间件
  next(err);
};

/**
 * 处理授权错误的中间件
 * @param {Object} err - 错误对象
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - Express下一个中间件函数
 */
const authErrorHandler = (err, req, res, next) => {
  // 检查是否为授权错误
  if (err.name === 'UnauthorizedError' || err.name === 'JsonWebTokenError') {
    // 记录授权错误
    logError(err, req);
    
    return res.status(401).json({
      message: '未授权访问，请登录',
    });
  }
  
  // 检查是否为权限错误
  if (err.name === 'ForbiddenError') {
    // 记录权限错误
    logError(err, req);
    
    return res.status(403).json({
      message: '无权限执行此操作',
    });
  }
  
  // 不是授权错误，传递给下一个错误处理中间件
  next(err);
};

/**
 * 处理数据库错误的中间件
 * @param {Object} err - 错误对象
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - Express下一个中间件函数
 */
const databaseErrorHandler = (err, req, res, next) => {
  // 检查是否为MongoDB重复键错误
  if (err.code === 11000) {
    const field = Object.keys(err.keyValue)[0];
    const value = err.keyValue[field];
    
    // 记录数据库错误
    logError(err, req);
    
    return res.status(409).json({
      message: '数据冲突',
      error: `${field} '${value}' 已存在`,
    });
  }
  
  // 检查是否为其他数据库错误
  if (err.name === 'MongoError' || err.name === 'MongooseError') {
    // 记录数据库错误
    logError(err, req);
    
    return res.status(500).json({
      message: '数据库操作失败',
      error: process.env.NODE_ENV === 'production' ? '请稍后再试' : err.message,
    });
  }
  
  // 不是数据库错误，传递给下一个错误处理中间件
  next(err);
};

/**
 * 通用错误处理中间件
 * @param {Object} err - 错误对象
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - Express下一个中间件函数
 */
const errorHandler = (err, req, res, next) => {
  // 记录错误
  const errorDetails = logError(err, req);
  
  // 如果状态码仍然是200，则设置为500
  const statusCode = res.statusCode === 200 ? 500 : res.statusCode;
  
  // 构建错误响应
  const errorResponse = {
    message: err.message || '服务器内部错误',
    status: statusCode,
    timestamp: new Date().toISOString(),
  };
  
  // 在非生产环境中添加错误堆栈
  if (process.env.NODE_ENV !== 'production') {
    errorResponse.stack = err.stack;
    errorResponse.details = errorDetails;
  }
  
  res.status(statusCode).json(errorResponse);
};

module.exports = { 
  notFound, 
  validationErrorHandler,
  authErrorHandler,
  databaseErrorHandler,
  errorHandler 
}; 